#pragma once

#include "../../Libs/headers.default.h"
#include "../../Libs/headers.classification.h"

using namespace loirey;

namespace datasets_taic
{
	class CSourceItem
	{
	public:
		int Label;
		int WordIndex;
		int HiddenRank;
		int InstanceAmount;
		CSparseVector FeatureList;

	public:
		CSourceItem();
		CSourceItem(int Label, int WordIndex, int HiddenRank, int SingleFeatureValue);
		void myInit(int Label, int WordIndex, int HiddenRank, int SingleFeatureValue);
		bool operator< (const CSourceItem& Another) const;
		int ComputeInstanceAmount();
	};

	class CSourceFeatureCountDataSet
	{
	public:
		int Size_C;
		int Size_F;
		int Size_W;
		//int Size_V;
		//int Size_X;
		CSimpleTypeArray<double> ListWC_P_w_given_c_D;
		CSimpleTypeArray<CSourceItem> List_Item;

	public:
		CSourceFeatureCountDataSet();
		void Clear();
		void myInit(string strFN_Data_WD, string strFN_Data_FWV);
		void SortItemList();
	public:
		void MakeFullImageExampleList(
			CWeightedClassificationExampleList& DstExampleList, bool fClearFirst,
			int MinWordIndexAllowed, int MaxWordIndexAllowed, int K) const;
		void MakeSingleClassImageExampleList(
			int Label, CWeightedClassificationExampleList& DstExampleList, bool fClearFirst,
			int MinWordIndexAllowed, int MaxWordIndexAllowed, int K) const;
	public:
		double GetP_w_given_c_D(int WordIndex, int Label) const;
		int LowerBound(int Label, int WordIndex, int HiddenRank = -1) const;
		int UpperBound(int Label, int WordIndex, int HiddenRank = 2147483647) const;
	public:
		void InitAndClearPureImageDataSet(
			int Size_C, int Size_F);
		void PushBackItem(
			const CSourceFeatureCountDataSet* pSrcFCDS, int ItemIndex,
			int Label, int WordIndex, int HiddenRank);
	};

	class C_FCDS_LabeledDataSetForClassification : public CLabeledDataSetForClassification
	{
	public:
		const CSourceFeatureCountDataSet* pFCDS;

	public:
		virtual void myInit(const CSourceFeatureCountDataSet* pFCDS);
	public:
		virtual int GetExampleLabel(int ExampleIndex);
	public:
		virtual int GetExampleAmount();
		virtual double GetExampleInitialWeight(int ExampleIndex);
		virtual int GetFeatureDimension();
		virtual double GetExampleFeature(int ExampleIndex, int FeatureIndex);
	};

	class CClassInformation
	{
	public:
		string strName;
		string strFCDS;
		int In_FCDS_Label;
		int FCDS_Index;
	};

	class CClassDataSet
	{
	public:
		string strName;
		string strPN_Base;
		string strFN_Data_WD;
		string strFN_Data_FWV;
		int ClassAmount;
		CSimpleTypeArray<CClassInformation> List_ClassInfo;
		CSimpleTypeArray<CSourceFeatureCountDataSet> List_FCDS;
		map<string, int> mapClassName;

	public:
		void myInit(string strFN_ClassLabel);
		int LoadFCDS(int ClassIndex);
		int GetClassIndex(string strClassName) const;
		const CSourceFeatureCountDataSet* GetPtrFCDS(int ClassIndex);
		const CSourceFeatureCountDataSet* GetPtrFCDS(string strClassName);
	};

	class CSingleClassNaiveBayesModel_TAIC
	{
	// Final Output
	public:
		int FeatureDimension;
		CSimpleTypeArray<double> vecF_P_f_given_c_V;
		CSimpleTypeArray<double> vecF_P_f_given_c_D;
		CSimpleTypeArray<double> vecF_logP_f_given_c_L;
	// Intermediate Output
	public:
		int SelectTopK;
		int WordDimension;
		double Lambda;
		CSimpleTypeArray<double> vecW_P_w_given_c_D;
		CSimpleTypeArray<double> matFW_P_f_given_w_c;

	public:
		CSingleClassNaiveBayesModel_TAIC();
		void Clear();
		void InitFeatureDimension(int FeatureDimension);
		void InitImageModel(
			const CSourceFeatureCountDataSet* pSrcFCDS, int Label,
			CWeightedClassificationExampleList& TrainImageExampleList,
			int MinWordIndexAllowed, int MaxWordIndexAllowed, int K);
		void InitTextModel(
			const CSourceFeatureCountDataSet* pSrcFCDS, int Label,
			int K, int W, double Threshold_PWC);
		void InitLambda(double Lambda);
	public:
		void SaveToFile(string strFN_Model) const;
		bool LoadFromFile(string strFN_Model);
	};

	class CTask_TAIC
	{
	public:
		CClassDataSet* pSrcClassDataSet;
		int ClassAmount;
		CSimpleTypeArray<int> List_ClassIndex;

	public:
		virtual bool myInit(
			CClassDataSet* pSrcClassDataSet,
			istream& inStream);
		virtual void MakeClassificationDataSet(
			CSourceFeatureCountDataSet& DstDataSet_Train, int BaseImageAmountPerClass_Train,
			CSourceFeatureCountDataSet& DstDataSet_Test, int BaseImageAmountPerClass_Test,
			int MinWordIndexAllowed, int MaxWordIndexAllowed, int K) const;
		virtual void TrainImageSVM(
			CSimpleTypeArray<CSVMLightHelper::CModel>& List_SVM,
			const CSourceFeatureCountDataSet& SrcInitializedDataSet_Train) const;
			//const CSourceFeatureCountDataSet& SrcInitializedDataSet_Train,
			//int MinWordIndexAllowed, int MaxWordIndexAllowed, int K) const;
		virtual void TrainImageModel(
			CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM,
			const CSourceFeatureCountDataSet& SrcInitializedDataSet_Train) const;
			//const CSourceFeatureCountDataSet& SrcInitializedDataSet_Train,
			//int MinWordIndexAllowed, int MaxWordIndexAllowed, int K) const;
		virtual void TrainTextModel(
			CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM,
			int K, int W, double Threshold_PWC) const;
		virtual void TrainMixedModel(
			CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM,
			double Lambda) const;
		void Test(
			const CSimpleTypeArray<CSVMLightHelper::CModel>& List_SVM,
			const CSourceFeatureCountDataSet& SrcInitializedDataSet_Test,
			double& DstAccuracy) const;
		void Test(
			const CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM,
			const CSourceFeatureCountDataSet& SrcInitializedDataSet_Test,
			double& DstAccuracy) const;
	};

	class CTaskSet_TAIC
	{
	public:
		int TaskAmount;
		CSimpleTypeArray<CTask_TAIC> List_Task;

	public:
		virtual void myInit(CClassDataSet* pSrcClassDataSet, string strFN_TaskSet);
	};

	//class CNaiveBayesMode_TAIC
	//{
	//public:
	//	int FeatureDimension;
	//	int WordDimension;
	//	int LabelAmount;
	//	CSimpleTypeArray<double> vecC_P_c_given_V;
	//	CSimpleTypeArray<double> vecC_P_c_given_D;
	//	CSimpleTypeArray<double> matFC_P_f_given_c_V;
	//	CSimpleTypeArray<double> matFC_P_f_given_c_D;
	//	CSimpleTypeArray<double> matWC_P_w_given_c_D;
	//	CSimpleTypeArray<double> matFWC_P_f_given_w_c;
	//public:
	//	double Lambda;
	//	CSimpleTypeArray<double> vecC_logP_c_given_L;
	//	CSimpleTypeArray<double> matFC_logP_f_given_c_L;

	//public:
	//	CNaiveBayesMode_TAIC();
	//public:
	//	void InitImageModel(
	//		const CSourceFeatureCountDataSet* pSrcFCDS,
	//		CWeightedClassificationExampleList& TrainImageExampleList);
	//	void InitTextModel(
	//		const CSourceFeatureCountDataSet* pSrcFCDS,
	//		int K, int W);
	//public:
	//	void SetLambda(double Lambda);
	//public:
	//	double GetP_f_given_c_V(int FeatureIndex, int Label) const;
	//	double GetP_f_given_c_D(int FeatureIndex, int Label) const;
	//	double GetLogP_f_given_c_L(int FeatureIndex, int Label) const;
	//public:
	//	void Test(
	//		const CSourceFeatureCountDataSet* pSrcFCDS,
	//		CWeightedClassificationExampleList& TestExampleList,
	//		double& DstAccuracy);
	//};
}

